import socket
import ssl
import os
import sys
import datetime
import argparse

def test_connection(server_ip, server_port, cert_path=None, timeout=5, allow_self_signed=False):
    print(f"测试连接到 {server_ip}:{server_port}...")
    print(f"超时设置: {timeout}秒")

    # 首先测试基本网络连接
    try:
        # 创建TCP套接字
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(timeout)
        print("正在尝试TCP连接...")
        result = sock.connect_ex((server_ip, server_port))

        if result != 0:
            print(f"TCP连接失败，错误码: {result}")
            print("可能的原因:")
            print("1. 服务器IP或端口不正确")
            print("2. 服务器未运行或未监听该端口")
            print("3. 网络连接问题或防火墙阻止")
            return False
        else:
            print("TCP连接成功！")

        # 如果提供了证书，测试SSL连接
        if cert_path:
            print("正在测试SSL连接...")
            try:
                # 检查证书文件是否存在
                if not os.path.exists(cert_path):
                    print(f"错误: 证书文件不存在: {cert_path}")
                    return False

                # 检查证书格式
                try:
                    context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
                    context.load_verify_locations(cert_path)
                    print("证书格式验证通过。")
                except ssl.SSLError as e:
                    print(f"证书格式错误: {str(e)}")
                    print("可能的原因: 证书文件损坏、格式不正确。")
                    return False

                # 创建SSL上下文
                context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
                
                # 如果允许自签名证书
                if allow_self_signed:
                    print("允许自签名证书模式已启用...")
                    context.check_hostname = False
                    context.verify_mode = ssl.CERT_NONE
                else:
                    context.load_verify_locations(cert_path)

                # 包装套接字
                secure_sock = context.wrap_socket(sock, server_hostname=server_ip)
                secure_sock.settimeout(timeout)

                # 进行SSL握手
                try:
                    print("正在进行SSL握手...")
                    secure_sock.do_handshake()
                    print("SSL握手成功！")

                    # 获取证书信息
                    cert = secure_sock.getpeercert()
                    print("\n证书信息:")
                    
                    # 在允许自签名证书模式下，证书信息可能不完整
                    if allow_self_signed:
                        print("注意: 在允许自签名证书模式下，证书信息可能不完整。")
                        if 'subject' in cert:
                            print(f"颁发给: {cert['subject']}")
                        if 'issuer' in cert:
                            print(f"颁发者: {cert['issuer']}")
                        if 'notBefore' in cert:
                            print(f"有效期从: {cert['notBefore']}")
                        if 'notAfter' in cert:
                            print(f"有效期至: {cert['notAfter']}")
                            # 检查证书是否过期
                            try:
                                not_after = datetime.datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
                                if datetime.datetime.utcnow() > not_after:
                                    print("警告: 证书已过期！")
                                else:
                                    print("证书未过期。")
                            except:
                                print("无法验证证书有效期。")
                        else:
                            print("无法获取证书有效期。")
                    else:
                        print(f"颁发给: {cert['subject']}")
                        print(f"颁发者: {cert['issuer']}")
                        print(f"有效期从: {cert['notBefore']}")
                        print(f"有效期至: {cert['notAfter']}")

                        # 检查证书是否过期
                        not_after = datetime.datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
                        if datetime.datetime.utcnow() > not_after:
                            print("警告: 证书已过期！")
                        else:
                            print("证书未过期。")

                    print(f"SSL版本: {secure_sock.version()}")
                    secure_sock.close()
                    return True
                except socket.timeout:
                    print("SSL握手超时！")
                    print("可能的原因:")
                    print("1. 服务器SSL配置问题")
                    print("2. 网络不稳定或速度慢")
                    print("3. 防火墙阻止SSL握手")
                    return False

            except ssl.SSLError as e:
                print(f"SSL错误: {str(e)}")
                print("可能的原因:")
                print("1. 证书不正确或已过期")
                print("2. 证书与服务器不匹配")
                print("3. 服务器配置不正确")
                return False
            except Exception as e:
                print(f"SSL连接测试失败: {str(e)}")
                return False
        else:
            sock.close()
            print("未提供证书，仅测试了TCP连接")
            return True

    except Exception as e:
        print(f"连接测试失败: {str(e)}")
        return False

if __name__ == "__main__":
    # 设置命令行参数
    parser = argparse.ArgumentParser(description='HTTPS连接测试工具')
    parser.add_argument('server_ip', nargs='?', default='192.168.43.1', help='服务器IP地址')
    parser.add_argument('server_port', nargs='?', default=443, type=int, help='服务器端口')
    parser.add_argument('cert_path', nargs='?', default=os.path.join(os.getcwd(), 'client.crt'), help='证书文件路径')
    parser.add_argument('timeout', nargs='?', default=5, type=int, help='超时时间(秒)')
    parser.add_argument('--allow-self-signed', action='store_true', help='允许自签名证书')
    args = parser.parse_args()

    # 提取参数
    server_ip = args.server_ip
    server_port = args.server_port
    cert_path = args.cert_path
    timeout = args.timeout
    allow_self_signed = args.allow_self_signed

    print("=== HTTPS连接测试工具 ===")
    print(f"服务器IP: {server_ip}")
    print(f"服务器端口: {server_port}")
    print(f"证书路径: {cert_path}")
    print("========================")
    if allow_self_signed:
        print("注意: 已启用允许自签名证书模式，这可能会带来安全风险！")

    success = test_connection(server_ip, server_port, cert_path, timeout, allow_self_signed)

    if success:
        print("测试成功！连接正常。")
    else:
        print("测试失败，请检查上述问题。")